home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / turbopas / sfmsrc.arc / SFMFUNC.INC < prev    next >
Text File  |  1987-11-15  |  24KB  |  960 lines

  1. {                        Super File Manager
  2.  
  3.                             SFMFUNC.INC
  4.  
  5.                          by David Steiner
  6.                             2035 J Apt. 6
  7.                             Lincoln, NE
  8.  
  9.  
  10.    These routines serve as an interface between the user and
  11.      the low level DOS calls located in sfmDOS.inc.  They also
  12.      call upon the routines in sfmSCRN.inc to help perform
  13.      input and output.
  14. }
  15.  
  16. function ChangePath( w : integer ) : boolean;
  17.   {
  18.   Prompt user to enter a new path for the window specified.
  19.   }
  20. var
  21.   tstr  : str80;
  22.   tw, i : integer;
  23.   err   : boolean;
  24. begin
  25.   err := true;
  26.   if loaded[w] then tw := w
  27.   else tw := 3 - w;
  28.   Wind( 3 );
  29.   clrscr;
  30.   writeln;
  31.   Disp( NATTR, ' Enter a new path > ' );
  32.   tstr := GetLine( X2 - wherex - 1 );
  33.   writeln;
  34.   if pos( ':', tstr ) = 0 then
  35.     i := ChangeCurDir( Path[tw] );
  36.   if tstr <> '' then
  37.   begin
  38.     i := ChangeCurDir( tstr );
  39.     if i <> 0 then
  40.       ErrorMessage( i )
  41.     else
  42.     begin
  43.       if Loaded[3-w] and (tstr = Path[3-w]) then
  44.         DupPathMessage
  45.       else
  46.       begin
  47.         err := false;
  48.         HelpScreen[w] := false;
  49.         Path[w] := tstr;
  50.         Drive[w] := GetCurDrive;
  51.         DiskFree[w] := FreeDisk( Drive[w] );
  52.         LoadDir( w );
  53.       end
  54.     end;
  55.   end;
  56.   ChangePath := not err;
  57. end;
  58.  
  59. function CountMarked( w : integer ) : integer;
  60.   {
  61.   Counts the number of marked files that are visible
  62.     through the current mask.
  63.   }
  64. var
  65.   i, j : integer;
  66. begin
  67.   i := NextEntry( w, 0 );
  68.   j := 0;
  69.   while i <> 0 do
  70.   begin
  71.     if Marked[w][i] then j := j + 1;
  72.     i := NextEntry( w, i );
  73.   end;
  74.   CountMarked := j;
  75. end;
  76.  
  77. procedure CopyMarked( w : integer );
  78.   {
  79.   Sets up the call to CopyEntries, which does all the real work.
  80.   }
  81. var
  82.   dest, tpath : str80;
  83.   i, j        : integer;
  84. begin
  85.   Wind( 3 );
  86.   clrscr;
  87.   writeln;
  88.   j := CountMarked( w );
  89.   if j <> 0 then
  90.   begin
  91.     Disp( NATTR, ' Copy ' );
  92.     Disp( HATTR, Cstr( j, 0, 0 ) );
  93.     Disp( NATTR, ' marked entries to ' );
  94.     dest := '';
  95.     if Loaded[3-w] then
  96.     begin
  97.       Disp( NATTR, Path[3-w] );
  98.       if YorN( true ) then dest := Path[3-w];
  99.     end;
  100.     writeln;
  101.     if dest = '' then
  102.     begin
  103.       Disp( NATTR, ' Destination path > ');
  104.       dest := GetLine( X2 - wherex - 1 );
  105.       writeln;
  106.     end;
  107.     if dest <> '' then
  108.     begin
  109.       if Path[3-w] = dest then
  110.       begin
  111.         i := 0;
  112.         j := Drive[3-w];
  113.       end
  114.       else
  115.       begin
  116.         if pos( ':', dest ) = 0 then
  117.           i := ChangeCurDir( Path[w] );
  118.         i := ChangeCurDir( dest );
  119.         j := GetCurDrive;
  120.       end;
  121.       if i <> 0 then
  122.          ErrorMessage( i )
  123.       else
  124.       begin
  125.         if dest <> Path[w] then
  126.         begin
  127.  
  128.           CopyEntries( w, dest, (dest = Path[3-w]) );
  129.  
  130.           if Drive[w] = j then
  131.           begin
  132.             DiskFree[w] := FreeDisk( j );
  133.             WriteSizes( w, true );
  134.           end;
  135.           if Loaded[3-w] and (Drive[3-w] = j) then
  136.           begin
  137.             if Drive[3-w] = Drive[w] then DiskFree[3-w] := DiskFree[w]
  138.             else DiskFree[3-w] := FreeDisk( j );
  139.             if Path[3-w] = dest then LoadDir( 3-w )
  140.             else WriteWindow( 3-w );
  141.           end;
  142.         end
  143.         else
  144.         begin
  145.           clrscr;
  146.           writeln;
  147.           Disp( NATTR, ' Error: ' );
  148.           Disp( HATTR, 'Destination path is same as source path.' );
  149.           writeln;
  150.           gotoxy( 9, wherey );
  151.           wait;
  152.         end;
  153.       end;
  154.     end;
  155.   end;
  156. end;
  157.  
  158. procedure DeleteMarked( w : integer );
  159.   {
  160.   Trash all the marked files that aren't masked out.
  161.   }
  162. var
  163.   tstr, tstr2 : str80;
  164.   i, err      : integer;
  165.   done        : boolean;
  166. begin
  167.   i := CountMarked( w );
  168.   if i <> 0 then
  169.   begin
  170.     Wind( 3 );
  171.     clrscr;
  172.     writeln;
  173.     Disp( NATTR, ' Delete ' );
  174.     Disp( HATTR, Cstr( i, 0, 0 ) );
  175.     Disp( NATTR, ' marked entries from ' + Path[w] );
  176.     if YorN( false ) then
  177.     begin
  178.       writeln;
  179.       tstr := Path[w];
  180.       if ord( tstr[0] ) <> 3 then tstr := tstr + '\';
  181.       i    := NextEntry( w, 0 );
  182.       done := false;
  183.       while (i <> 0) and not done do
  184.       begin
  185.         if Marked[w][i] then
  186.         begin
  187.           tstr2 := ConvertName( Entry[w][i] );
  188.           clrscr;
  189.           writeln;
  190.           Disp( NATTR, ' Deleting file ' );
  191.           Disp( HATTR, tstr + tstr2 );
  192.           err := DeleteFile( tstr + tstr2 );
  193.           if err <> 0 then
  194.           begin
  195.             ErrorMessage( err );
  196.             done := not Continue;
  197.           end
  198.           else
  199.             Entry[w][i].Name[1] := DelChar;
  200.         end;
  201.         i := NextEntry( w, i );
  202.       end;
  203.       DiskFree[w] := FreeDisk( Drive[w] );
  204.       if (Drive[3-w] = Drive[w]) and Loaded[3-w] then
  205.       begin
  206.         DiskFree[3-w] := DiskFree[w];
  207.         WriteSizes( 3-w, not HelpScreen[3-w] );
  208.       end;
  209.       DirSize[w] := TallySizes( w );
  210.       HomeKey( w );
  211.     end;
  212.   end;
  213. end;
  214.  
  215. procedure FixWindow( w : integer );
  216.   {
  217.   This isn't a very good name, but the procedure removes the
  218.     current entry from the window and then updates without
  219.     sending the user clear to the begining of the directory.
  220.   }
  221. var
  222.   i : integer;
  223. begin
  224.   Entry[w][CurEntry[w]].Name[1] := DelChar;
  225.   i := LastEntry( w, TopEntry[w] );
  226.   if i <> 0 then
  227.   begin
  228.     TopEntry[w] := i;
  229.     CurEntry[w] := LastEntry( w, CurEntry[w] );
  230.   end
  231.   else
  232.   begin
  233.     if CurEntry[w] = TopEntry[w] then
  234.     begin
  235.       TopEntry[w] := NextEntry( w, TopEntry[w] );
  236.       CurEntry[w] := TopEntry[w];
  237.     end
  238.     else
  239.     begin
  240.       CurLin[w] := CurLin[w] - 1;
  241.       CurEntry[w] := LastEntry( w, CurEntry[w] );
  242.     end;
  243.   end;
  244.   DiskFree[w] := FreeDisk( Drive[w] );
  245.   if (Drive[3-w] = Drive[w]) and Loaded[3-w] then
  246.   begin
  247.     DiskFree[3-w] := DiskFree[w];
  248.     WriteSizes( 3-w, not HelpScreen[3-w] );
  249.   end;
  250.   DirSize[w] := TallySizes( w );
  251.   WriteWindow( w );
  252. end;
  253.  
  254. procedure DeleteEntry( w : integer );
  255.   {
  256.   Sets up the deletion of a single entry.  If it is a file
  257.     then we call DeleteFile, if it is a directory then we
  258.     must call RemDir instead.
  259.   }
  260. var
  261.   tstr, tstr2 : str80;
  262.   err         : integer;
  263.   dir         : boolean;
  264. begin
  265.   if CurEntry[w] <> 0 then
  266.   begin
  267.     dir := ( ( Entry[w][CurEntry[w]].Attr AND Dbit ) <> 0 );
  268.     Wind( 3 );
  269.     clrscr;
  270.     writeln;
  271.     tstr := Path[w];
  272.     if ord( tstr[0] ) <> 3 then tstr := tstr + '\';
  273.     tstr2 := ConvertName( Entry[w][CurEntry[w]] );
  274.     if dir then
  275.       Disp( NATTR, ' Remove directory ' )
  276.     else
  277.       Disp( NATTR, ' Delete file ' );
  278.     Disp( NATTR, tstr + tstr2 );
  279.     if YorN( false ) then
  280.     begin
  281.       writeln;
  282.       if dir then
  283.       begin
  284.         err := ChangeCurDir( tstr );
  285.         err := RemDir( tstr + tstr2 );
  286.       end
  287.       else
  288.         err := DeleteFile( tstr + tstr2 );
  289.       if err <> 0 then
  290.         ErrorMessage( err )
  291.       else
  292.       begin
  293.         FixWindow( w );
  294.         if dir and Loaded[3-w] and (tstr+tstr2 = Path[3-w]) then
  295.         begin
  296.           Loaded[3-w] := false;
  297.           HelpWindow( w, 3-w );
  298.         end;
  299.       end;
  300.     end;
  301.   end;
  302. end;
  303.  
  304. procedure RenameEntry( w : integer );
  305.   {
  306.   Rename a file directly on the disk.
  307.   }
  308. var
  309.   tpath, told, tnew : str80;
  310.   i                 : integer;
  311. begin
  312.   if CurEntry[w] <> 0 then
  313.   begin
  314.     tpath := Path[w];
  315.     if ord( tpath[0] ) <> 3 then
  316.       tpath := tpath + '\';
  317.     told := ConvertName( Entry[w][CurEntry[w]] );
  318.     Wind( 3 );
  319.     clrscr;
  320.     writeln;
  321.     Disp( NATTR, ' Rename ' + told + ' as > ' );
  322.     tnew := GetLine( 12 );
  323.     writeln;
  324.     if tnew <> '' then
  325.     begin
  326.       i := RenameFile( tpath + told, tpath + tnew );
  327.       if i <> 0 then
  328.         ErrorMessage( i )
  329.       else
  330.       begin
  331.         if ParseFileName( tnew,addr( Entry[w][CurEntry[w]].Name[1] ) ) then;
  332.         Wind( w );
  333.         gotoxy( 1, CurLin[w] );
  334.         WriteEntry( Marked[w][CurEntry[w]], Entry[w][CurEntry[w]] );
  335.       end;
  336.     end;
  337.   end;
  338. end;
  339.  
  340. procedure RedirectMarked( w : integer );
  341.   {
  342.   Move the marked entries from one directory to another on
  343.     a disk.  Doesn't actually copy the files, just their
  344.     directory entries.
  345.   }
  346. var
  347.   tstr, fpath, topath : str80;
  348.   i, j                : integer;
  349.   done, reload        : boolean;
  350. begin
  351.   i := CountMarked( w );
  352.   if i <> 0 then
  353.   begin
  354.     Wind( 3 );
  355.     clrscr;
  356.     writeln;
  357.     Disp( NATTR, ' Move ' );
  358.     Disp( HATTR, Cstr( i, 0, 0 ) );
  359.     Disp( NATTR, ' marked entries to ' );
  360.     topath := '';
  361.     if Loaded[3-w] and (Drive[w] = Drive[3-w]) then
  362.     begin
  363.       Disp( NATTR, Path[3-w] );
  364.       if YorN( false ) then topath := Path[3-w];
  365.     end;
  366.     writeln;
  367.     if topath = '' then
  368.     begin
  369.       i := ChangeCurDir( Path[w] );
  370.       Disp( NATTR, ' Destination path > ' );
  371.       topath := GetLine( X2 - wherex - 1 );
  372.       writeln;
  373.       i := ChangeCurDir( topath );
  374.       if i <> 0 then
  375.       begin
  376.         ErrorMessage( i );
  377.         topath := '';
  378.       end;
  379.     end;
  380.     if (Path[w] <> topath) and (topath <> '') then
  381.     begin
  382.       fpath := Path[w];
  383.       reload := (topath = Path[3-w]);
  384.       if ord( topath[0] ) <> 3 then topath := topath + '\';
  385.       if ord( fpath[0]  ) <> 3 then fpath  := fpath  + '\';
  386.       i    := NextEntry( w, 0 );
  387.       done := false;
  388.       while (i <> 0) and not done do
  389.       begin
  390.         if Marked[w][i] then
  391.         begin
  392.           clrscr;
  393.           writeln;
  394.           tstr := ConvertName( Entry[w][i] );
  395.           Disp( NATTR, ' Moving file ' );
  396.           Disp( HATTR, tstr );
  397.           Disp( NATTR, ' to ' );
  398.           Disp( HATTR, topath );
  399.           j := RenameFile( fpath + tstr, topath + tstr );
  400.           if j <> 0 then
  401.           begin
  402.             ErrorMessage( j );
  403.             done := not Continue;
  404.           end
  405.           else
  406.             Entry[w][i].Name[1] := DelChar;
  407.         end;
  408.         i := NextEntry( w, i );
  409.       end;
  410.       DirSize[w] := TallySizes( w );
  411.       HomeKey( w );
  412.       if reload then LoadDir( 3-w );
  413.     end;
  414.   end;
  415. end;
  416.  
  417. procedure Sort( w : integer );
  418.   {
  419.   Set up call to InsertSort.
  420.   }
  421. const
  422.   field  : integer = 1;
  423.   forwrd : boolean = true;
  424.   fwd    : array[false..true] of string[7] = ('Reverse','Forward');
  425. var
  426.   tstr   : str80;
  427.   x, y   : integer;
  428.   ch     : char;
  429. begin
  430.   if MaxEntry[w] > 1 then
  431.   begin
  432.     Wind( 3 );
  433.     clrscr;
  434.     writeln;
  435.     Disp( NATTR, ' Select sort field > ' );
  436.     x := wherex;
  437.     y := wherey;
  438.     repeat
  439.       gotoxy( x, y );
  440.       clreol;
  441.       case field of
  442.         0 : tstr := 'Attribute (sys,vol,dir,norm,hid,del)';
  443.         1 : tstr := 'Name';
  444.         2 : tstr := 'Extension';
  445.         3 : tstr := 'Size';
  446.         4 : tstr := 'Date and Time';
  447.       end;
  448.       Disp( HATTR, tstr );
  449.       ch := KeyboardNorm;
  450.       case upcase(ch) of
  451.         'A' : field := 0;
  452.         ' ',
  453.         '+' : if field = 4 then field := 0 else field := field + 1;
  454.         'N' : field := 1;
  455.         'E' : field := 2;
  456.         'S' : field := 3;
  457.         'D',
  458.         'T' : field := 4;
  459.       end;
  460.     until ch in [#27,#13];
  461.     if (ch <> #27) and (field <> 0) then
  462.     begin
  463.       writeln;
  464.       writeln;
  465.       Disp( NATTR, ' Select sort order > ' );
  466.       x := wherex;
  467.       y := wherey;
  468.       repeat
  469.         gotoxy( x, y );
  470.         Disp( HATTR, fwd[forwrd] );
  471.         ch := KeyboardNorm;
  472.         case upcase(ch) of
  473.           ' ',
  474.           '+' : forwrd := not forwrd;
  475.           'F' : forwrd := true;
  476.           'R' : forwrd := false;
  477.         end;
  478.       until ch in [#13, #27];
  479.     end;
  480.     if ch <> #27 then
  481.     begin
  482.       if field <> 0 then
  483.         InsertSort( w, field, forwrd );
  484.       InsertSort( w, 0, true );
  485.       HomeKey( w );
  486.       Saved[w] := false;
  487.     end;
  488.   end;
  489. end;
  490.  
  491. procedure SetMask( w : integer );
  492.   {
  493.   Set mask to determine what files will be displayed in the window.
  494.   }
  495. var
  496.   tstr : str80;
  497. begin
  498.   Wind( 3 );
  499.   clrscr;
  500.   writeln;
  501.   Disp( NATTR, ' Enter a new mask > ' );
  502.   tstr := GetLine( 12 );
  503.   if tstr <> '' then
  504.   begin
  505.     if ParseFileName( tstr, addr( ConvMask[w][1] ) ) then
  506.     begin
  507.       Mask[w] := tstr;
  508.       HomeKey( w );
  509.     end;
  510.   end;
  511. end;
  512.  
  513. procedure MakeDir( w : integer );
  514.   {
  515.   Set up call to MakDir.
  516.   }
  517. var
  518.   tstr        : str80;
  519.   drv, err, i : integer;
  520.   fr          : real;
  521. begin
  522.   Wind( 3 );
  523.   clrscr;
  524.   writeln;
  525.   Disp( NATTR, ' Enter path to create > ' );
  526.   tstr := GetLine( X2 - wherex - 1 );
  527.   writeln;
  528.   if tstr <> '' then
  529.   begin
  530.     if pos( ':', tstr ) = 0 then
  531.       err := ChangeCurDir( Path[w] );
  532.     err := MakDir( tstr );
  533.     if err <> 0 then
  534.       ErrorMessage( err )
  535.     else
  536.     begin
  537.       err  := ChangeCurDir( tstr );
  538.       tstr := '..';
  539.       err  := ChangeCurDir( tstr );
  540.       drv  := GetCurDrive;
  541.       fr   := FreeDisk( drv );
  542.       for i := 1 to 2 do
  543.       begin
  544.         if Loaded[i] then
  545.         begin
  546.           if Drive[i] = drv then DiskFree[i] := fr;
  547.           if Path[i] = tstr then LoadDir( i )
  548.           else WriteSizes( i, not HelpScreen[i] );
  549.         end;
  550.       end;
  551.     end;
  552.   end;
  553. end;
  554.  
  555. procedure WriteDir( w : integer );
  556.   {
  557.   Determine whether or not saving the directory to disk
  558.     is allowed and then make proper calls as per
  559.     root or subdirectory.
  560.   }
  561. var
  562.   err : integer;
  563. begin
  564.   Wind( 3 );
  565.   clrscr;
  566.   writeln;
  567.   if NoSave[w] then
  568.   begin
  569.     Disp( NATTR, ' Error: ' );
  570.     Disp( HATTR, 'Save option was disabled - directory too large.' );
  571.     writeln;
  572.     gotoxy( 9, wherey );
  573.     wait;
  574.   end
  575.   else
  576.   begin
  577.     Disp( NATTR, ' Update directory ' + Path[w] + ' on disk' );
  578.     if YorN( false ) then
  579.     begin
  580.       writeln;
  581.       err := ChangeCurDir( Path[w] );
  582.       if err <> 0 then
  583.         ErrorMessage( err )
  584.       else
  585.       begin
  586.         if ord( Path[w][0] ) = 3 then
  587.           SaveRoot( w )
  588.         else
  589.           SaveSubDir( w );
  590.         Saved[w] := true;
  591.         if not FATsaved then SaveFAT( DiskTable[w], FATptr );
  592.         FATsaved := true;
  593.       end;
  594.     end;
  595.   end;
  596. end;
  597.  
  598. procedure UndeleteEntry( w : integer );
  599.   {
  600.   Check if file can be recovered and then get a new
  601.     first character.
  602.   }
  603. var
  604.   tstr    : str80;
  605.   amt, x  : integer;
  606.   ch      : char;
  607.   GotIt   : boolean;
  608. begin
  609.   if Entry[w][CurEntry[w]].Name[1] = DelChar then
  610.   begin
  611.     Wind( 3 );
  612.     clrscr;
  613.     writeln;
  614.     if NoSave[w] then
  615.     begin
  616.       Disp( NATTR, ' Error: ' );
  617.       Disp( HATTR, 'Option was disabled - directory was too large.' );
  618.       writeln;
  619.       gotoxy( 9, wherey );
  620.       wait;
  621.     end
  622.     else
  623.     begin
  624.       tstr := ConvertName( Entry[w][CurEntry[w]] );
  625.       Disp( NATTR, ' Attempt to recover file ' + tstr );
  626.       if YorN( true ) then
  627.       begin
  628.         writeln;
  629.         with DiskTable[w]^ do
  630.           amt := FATSIZE * SECTORSIZE;
  631.         if MemoryAvail < amt then
  632.         begin
  633.           Disp( NATTR, ' Error: ' );
  634.           Disp( HATTR, 'Insufficient memory for temporary FAT, aborted.' );
  635.           writeln;
  636.           gotoxy( 9, wherey );
  637.           wait;
  638.         end
  639.         else
  640.         begin
  641.           GotIt := UnDel( w );
  642.           if GotIt then
  643.           begin
  644.             FATsaved := false;
  645.             Saved[w] := false;
  646.             Disp(NATTR,' Recovery seems successful, check file to be certain.');
  647.             writeln;
  648.             repeat
  649.               writeln;
  650.               Disp( NATTR, ' Type first character > ' );
  651.               x := wherex;
  652.               Disp( HATTR, tstr );
  653.               gotoxy( x, wherey );
  654.               repeat
  655.                 ch := KeyboardNorm;
  656.                 ch := UpCase( ch );
  657.               until CharValid( ch );
  658.               Disp( HATTR, ch );
  659.               writeln;
  660.             until not CheckMatch( w, ch + copy( tstr, 2, 12 ) );
  661.             Entry[w][CurEntry[w]].Name[1] := ch;
  662.             Wind( w );
  663.             gotoxy( 1, CurLin[w] );
  664.             WriteEntry( false, Entry[w][CurEntry[w]] );
  665.             DirSize[w] := TallySizes( w );
  666.             WriteSizes( w, true );
  667.           end
  668.           else
  669.           begin
  670.             Disp( NATTR, ' Error: ' );
  671.             Disp( HATTR, 'File has been overwritten, recovery not possible.' );
  672.             writeln;
  673.             gotoxy( 9, wherey );
  674.             wait;
  675.           end
  676.         end;
  677.       end;
  678.     end;
  679.   end;
  680. end;
  681.  
  682. procedure Purge( w : integer );
  683.   {
  684.   Clear out all the deleted files that show up on menu
  685.     two all the time.
  686.   }
  687. var
  688.   i, j : integer;
  689. begin
  690.   j := 0;
  691.   for i := 1 to MaxEntry[w] do
  692.     if Entry[w][i].Name[1] = DelChar then j := j + 1;
  693.   if j <> 0 then
  694.   begin
  695.     Wind( 3 );
  696.     clrscr;
  697.     writeln;
  698.     Disp( NATTR, ' Purge ' );
  699.     Disp( HATTR, Cstr( j, 0, 0 ) );
  700.     Disp( NATTR, ' deleted file entries from ' + Path[w] );
  701.     if YorN( true ) then
  702.     begin
  703.       Saved[w] := false;
  704.       RemoveDeleted( w );
  705.       HomeKey( w );
  706.     end;
  707.   end;
  708. end;
  709.  
  710. procedure ToggleAttr( w : integer );
  711.   {
  712.   Check wich attribute should be toggled and then make
  713.     the appropriate call to ChangeAttr.
  714.   }
  715. const
  716.   atnum : integer = 1;
  717. var
  718.   tstr     : str80;
  719.   x, y, i  : integer;
  720.   newattr  : byte;
  721.   ch       : char;
  722. begin
  723.   if CurEntry[w] <> 0 then
  724.   begin
  725.     Wind( 3 );
  726.     clrscr;
  727.     writeln;
  728.     Disp( NATTR, ' Select attribute to toggle > ' );
  729.     x := wherex;
  730.     y := wherey;
  731.     begin
  732.       repeat
  733.         gotoxy( x, y );
  734.         clreol;
  735.         case atnum of
  736.           0 : Disp( HATTR, 'Archive' );
  737.           1 : Disp( HATTR, 'Hidden' );
  738.           2 : Disp( HATTR, 'Read-only' );
  739.         end;
  740.         ch := KeyboardNorm;
  741.         case upcase(ch) of
  742.           ' ',
  743.           '+' : if atnum = 2 then atnum := 0 else atnum := atnum + 1;
  744.           'A' : atnum := 0;
  745.           'H' : atnum := 1;
  746.           'R' : atnum := 2;
  747.         end;
  748.       until ch in [#13,#27];
  749.       if ch <> #27 then
  750.       begin
  751.         writeln;
  752.         case atnum of
  753.           0 : newattr := Entry[w][CurEntry[w]].Attr XOR Abit;
  754.           1 : newattr := Entry[w][CurEntry[w]].Attr XOR Hbit;
  755.           2 : newattr := Entry[w][CurEntry[w]].Attr XOR Rbit;
  756.         end;
  757.         tstr := Path[w];
  758.         if ord( tstr[0] ) <> 3 then tstr := tstr + '\';
  759.         tstr := tstr + ConvertName( Entry[w][CurEntry[w]] );
  760.         i := ChangeAttr( tstr, newattr );
  761.         if i <> 0 then
  762.           ErrorMessage( i )
  763.         else
  764.         begin
  765.           Entry[w][CurEntry[w]].Attr := newattr;
  766.           Wind( w );
  767.           gotoxy( 1, CurLin[w] );
  768.           WriteEntry( Marked[w][CurEntry[w]], Entry[w][CurEntry[w]] );
  769.         end;
  770.       end;
  771.     end;
  772.   end;
  773. end;
  774.  
  775. procedure ClearDisk( var w : integer );
  776.   {
  777.   Allows clearing of the floppy drives only.  We want to
  778.     be real careful about allowing people to wipe something out.
  779.   }
  780. const
  781.   d : integer = 1;
  782. var
  783.   drv       : integer;
  784.   disktable : DskTblptr;
  785. begin
  786.   Wind( 3 );
  787.   clrscr;
  788.   writeln;
  789.   Disp( NATTR, ' Warning: ' );
  790.   Disp( HATTR, 'Data on disk will be overwritten (ESC to abort function).' );
  791.   writeln;
  792.   writeln;
  793.   Disp( NATTR, ' Select floppy drive to CLEAR > ' );
  794.   drv := SelectFloppy( d );
  795.   if drv <> 0 then
  796.   begin
  797.     d := drv;
  798.     writeln;
  799.     Disp( NATTR, ' Insert disk and ' );
  800.     wait;
  801.     writeln;
  802.     GetTable( drv, disktable );
  803.     ClearFAT( drv, disktable );
  804.     if Loaded[w] and (Drive[w] = drv) then
  805.     begin
  806.       Path[w] := copy( Path[w], 1, 3 );
  807.       ReloadDir( w, 1 );
  808.     end;
  809.     if Loaded[3-w] and (Drive[3-w] = drv) then
  810.     begin
  811.       if Drive[3-w] = Drive[w] then
  812.       begin
  813.         Loaded[3-w] := false;
  814.         HelpWindow( w, 3-w );
  815.       end
  816.       else
  817.       begin
  818.         Path[3-w] := copy( Path[3-w], 1, 3 );
  819.         ReloadDir( 3-w, 1 );
  820.       end;
  821.     end;
  822.   end;
  823. end;
  824.  
  825. procedure ChangeName( w : integer );
  826.   {
  827.   Allow user to rename most entries to anything they can type
  828.     at the keyboard.
  829.     Exceptions:  '.' and '..' are reserved entries
  830.           Also:  names containing a period are formatted as DOS would
  831.   }
  832. var
  833.   tstr : str80;
  834.   i, j : integer;
  835. begin
  836.   if CurEntry[w] <> 0 then
  837.   begin
  838.     tstr := ConvertName( Entry[w][CurEntry[w]] );
  839.     if (tstr <> '.') and (tstr <> '..') then
  840.     begin
  841.       Wind( 3 );
  842.       clrscr;
  843.       writeln;
  844.       Disp( NATTR, ' Rename ' + tstr );
  845.       writeln;
  846.       Disp( NATTR, '   as > ' );
  847.       tstr := GetLine( 12 );
  848.       j    := pos( '.', tstr );
  849.       if (tstr <> '') and (j <> 1) then
  850.       begin
  851.  
  852.         for i := 1 to ord( tstr[0] ) do
  853.           tstr[i] := UpCase( tstr[i] );
  854.         if j = 0 then
  855.           tstr := copy( tstr, 1, 8 )
  856.         else
  857.         begin
  858.           for i := j to 8 do
  859.             insert( ' ', tstr, i );
  860.           delete( tstr, 9, pos( '.', tstr ) - 8 );
  861.         end;
  862.  
  863.         if Entry[w][CurEntry[w]].Name[1] = DelChar then tstr[1] := DelChar;
  864.         tstr := tstr + '            ';
  865.         move( tstr[1], Entry[w][CurEntry[w]].Name[1], 11 );
  866.         Wind( w );
  867.         gotoxy( 1, CurLin[w] );
  868.         WriteEntry( false, Entry[w][CurEntry[w]] );
  869.         Saved[w] := false;
  870.       end;
  871.     end;
  872.   end;
  873. end;
  874.  
  875. procedure VolLabel( w : integer );
  876.   {
  877.   Allow the deletion, creation or renaming of the volume
  878.     label if the current directory is the root.
  879.   }
  880. var
  881.   tstr : str80;
  882.   i    : integer;
  883.   done : boolean;
  884. begin
  885.   done := false;
  886.   Wind( 3 );
  887.   clrscr;
  888.   writeln;
  889.   if ord( Path[w][0] ) <> 3 then
  890.   begin
  891.     Disp( NATTR, ' Error: ' );
  892.     Disp( HATTR, 'Volume label only valid in root directory' );
  893.     writeln;
  894.     gotoxy( 9, wherey );
  895.     wait;
  896.   end
  897.   else
  898.   begin
  899.     i := 1;
  900.     while ( ((Entry[w][i].Attr AND Vbit) = 0)
  901.             or (Entry[w][i].Name[1] = DelChar) ) and (i <= MaxEntry[w]) do
  902.       i := i + 1;
  903.     if i > MaxEntry[w] then i := 0;
  904.     if i <> 0 then
  905.     begin
  906.       Disp( NATTR, ' Delete old label, ' + ConvertName( Entry[w][i] ) );
  907.       done := YorN( false );
  908.       if done then
  909.       begin
  910.         Entry[w][i].Name[1] := DelChar;
  911.         i := 0;
  912.         Saved[w] := false;
  913.       end;
  914.     end;
  915.     if not done then
  916.     begin
  917.       clrscr;
  918.       writeln;
  919.       if i <> 0 then
  920.         Disp( NATTR, ' Current label is  ' + ConvertName( Entry[w][i] ) )
  921.       else
  922.         Disp( NATTR, ' There is no current label.' );
  923.       writeln;
  924.       Disp( NATTR,   ' Enter new label > ' );
  925.       tstr := GetLine( 11 );
  926.       if tstr <> '' then
  927.       begin
  928.         if i = 0 then
  929.         begin
  930.           repeat
  931.             i := i + 1;
  932.           until (Entry[w][i].Name[1] = DelChar) or (i > MaxEntry[w]);
  933.           if (i > MaxEntry[w]) then
  934.           begin
  935.             if (i <= MaxFiles) then
  936.               MaxEntry[w] := i
  937.             else
  938.               i := 0;
  939.           end;
  940.         end;
  941.         if i <> 0 then
  942.         begin
  943.           with Entry[w][i] do
  944.           begin
  945.             tstr    := tstr + '           ';
  946.             Attr    := Vbit;
  947.             Time    := SysTime;
  948.             Date    := SysDate;
  949.             Cluster := 0;
  950.             Size[0] := 0;
  951.             Size[1] := 0;
  952.             move( tstr[1], Name[1], 11 );
  953.           end;
  954.           Saved[w] := false;
  955.         end;
  956.       end;
  957.     end;
  958.     HomeKey( w );
  959.   end;
  960. end;